/************************************************************************
 * @file		Exception.h
 * @brief	Exceptions defined by the engine
 *
 ************************************************************************/
#ifndef EXCEPTION_HPP
#define EXCEPTION_HPP

////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <exception>
#include <string>

namespace smeg
{
    namespace tools
    {
        ////////////////////////////////////////////////////////////
        /// Base class for exceptions
        ////////////////////////////////////////////////////////////
        class Exception :
        public std::exception
        {
        public:

            ////////////////////////////////////////////////////////////
            /// Default Constructor
            ///
            /// \param _message :   Exception message
            ///
            ////////////////////////////////////////////////////////////
            Exception( const std::string& _Message = "" );
            
            ////////////////////////////////////////////////////////////
            /// Virtual Destructor
            ///
            ////////////////////////////////////////////////////////////
            virtual ~Exception() throw ();

            ////////////////////////////////////////////////////////////
            /// Send back the message associated to the exception
            ///
            /// \return The message associated to the exception
            ///
            ////////////////////////////////////////////////////////////
            virtual const char* what() const throw ();

        protected:
            std::string m_Message; /// Message associated to the exception
        };

        ////////////////////////////////////////////////////////////
        /// Exception thrown if a condition isn't verified
        ////////////////////////////////////////////////////////////
        struct AssertException : public Exception
        {
            ////////////////////////////////////////////////////////////
            /// Constructor
            ///
            /// \param _File :      Source file with the error
            /// \param _iLine :     Line where the error is in the source file
            /// \param _Message :   Error message
            ///
            ////////////////////////////////////////////////////////////
            AssertException( const std::string& _File, int _iLine, const std::string & _Message );
        };

#ifdef _DEBUG
#define Assert(condition) if (!(condition)) throw AssertException( __FILE__, __LINE__, "Condition unsatisfied\n\n" #condition )
#else
#define Assert(condition)
#endif

        ////////////////////////////////////////////////////////////
        /// Memory allocation anomaly
        ////////////////////////////////////////////////////////////
        struct BadDelete : public Exception
        {
            ////////////////////////////////////////////////////////////
            /// Constructor
            ///
            /// \param _pPtr :      Bloc address
            /// \param _File :      Source file with the error
            /// \param _iLine :     Line where the error is in the source file
            /// \param _bNewArray : Indicate whether the [] is on the new or the delete
            ///
            ////////////////////////////////////////////////////////////
            BadDelete( const void* _pPtr, const std::string& _File, int Line, bool _bNewArray );
        };

        ////////////////////////////////////////////////////////////
        /// Exception thrown when loading files' error
        ////////////////////////////////////////////////////////////
        struct LoadingFailed : public Exception
        {
            ////////////////////////////////////////////////////////////
            /// Constructor
            ///
            /// \param _File :      Source file with the error
            /// \param _Message :   Error Message
            ///
            ////////////////////////////////////////////////////////////
            LoadingFailed( const std::string& _File, const std::string & _Message );
        };

        ////////////////////////////////////////////////////////////
        /// Exception thrown when out of memory
        ////////////////////////////////////////////////////////////
        struct OutOfMemory : public Exception
        {
            ////////////////////////////////////////////////////////////
            /// Constructor
            ///
            /// \param _Message :   Error Message
            ///
            ////////////////////////////////////////////////////////////
            OutOfMemory( const std::string & _Message );
        };
        
    } // namespace tools
} // namespace smeg

#endif // EXCEPTION_HPP
